package com.example.lottery_system.common.utils;


import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.json.JsonParseException;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.Callable;

/**
 * 单例进行序列化和反序列化
 */
@Component
public class JacksonUtil {
    private JacksonUtil() {

    }
    private static final  ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private static ObjectMapper getObjectMapper() {
        OBJECT_MAPPER.registerModule(new JavaTimeModule());
        OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return OBJECT_MAPPER;
    }


    // 尝试转化
    private static<T> T  tryParse(Callable<T> parser, Class<? extends Exception> check)  {
        try {
            return parser.call();
        } catch (Exception e) {
//            如果是这个类的异常
            if (check.isAssignableFrom(e.getClass())) {
                throw new JsonParseException(e);
            }

            // 否则就抛出其他异常
            throw new IllegalStateException(e);
        }
    }

    private static<T> T tryParse(Callable<T> parser) {

        return  tryParse(parser, JacksonException.class);
    }

    /**
     * 序列化
     * @param object
     * @return
     */

    public static String writeValueAsString(Object object) {
       String ret =   tryParse(()->{
            return getObjectMapper().writeValueAsString(object);
        });

       return ret;
    }



    /**
     * 反序列化
     * @param content   数据的内容
     * @param valueType 数据的类型
     * @return          返回该数据的类型
     * @param <T>
     */

    public static<T> T readValue(String content, Class<T> valueType) {
         T ret = tryParse(()->{
            return getObjectMapper().readValue(content,valueType);
        });

        return ret;
    }

    /**
     * list 的反序列化
     * 1. 从ObjectMapper 获取类型工厂
     * 2.  类型工厂中的 constructType方法（java的类对象， 参数对象）
     * 3. 最终得到 JavaType 来转化
     * @param content
     * @param paramClasses
     * @return
     * @param <T>
     */


    public  static<T> T readListValue(String content,Class<?> paramClasses) {

        JavaType javaType = getObjectMapper().getTypeFactory().constructParametricType(List.class,paramClasses);

        return tryParse(()->{
            return getObjectMapper().readValue(content,javaType);
        });
    }
}
